package com.scy.edu;

import com.scy.edu.client.RpcConsumer;
import com.scy.edu.handler.UserClientHandler;
import com.scy.edu.service.UserService;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 司晨雨
 * @date 2020/8/20 23:04
 * @description
 */
public class ConsumerBoot {

    private static Map<String, UserClientHandler> cmap =new HashMap<String, UserClientHandler>();

    //缓存服务注册信息
    private volatile static Map<String,Object> zkMap = new HashMap<String,Object>();
    //zk实例
    private static ZkClient zkClient;

    public static void main(String[] args) throws InterruptedException {

        zkClient = new ZkClient("127.0.0.1:2181");
        //加载zk服务注册信息
        getServerInfo();
        while (true){
            List<String> errorServices = new ArrayList();
            for(String serviceName : zkMap.keySet()){
                String address = (String)zkMap.get(serviceName);
                //创建代理对象
                System.out.println(address);
                System.out.println( Integer.parseInt(address.split(":")[1]));
                System.out.println(address.split(":")[0]);
                RpcConsumer rpcConsumer = new RpcConsumer(address.split(":")[0], Integer.parseInt(address.split(":")[1]));
                UserService userService = (UserService) rpcConsumer.createProxy(UserService.class);
                String result;
                try{
                    //调用服务
                    result = userService.sayHello(serviceName);
                }catch (Exception e){
                    System.out.println(e);
                    //异常则说明服务不通或已下线
                    result = "exception";
                }
                System.out.println(serviceName+"调用结果为"+result);
                if("exception".equals(result) || "timeout".equals(result)){
                    errorServices.add(serviceName);
                    System.out.println("服务名:"+serviceName+"调用服务异常,停止调用,等待zk下线改地址");
                }
            }
            //服务下线时将customMap中的服务端代理移除,当zk延迟感应到服务下线时,会重新获取服务信息,就会更新zkMap,同时也会更新customMap
            for (String errorService : errorServices) {
                zkMap.remove(errorService);
            }
            Thread.sleep(2000);
        }
    }

    //获取服务注册信息
    private static void getServerInfo(){
        cmap.clear();
        //获取服务列表
        List<String> servicesList = zkClient.getChildren("/lgServer");
        //添加监听,用于发现服务
        zkClient.subscribeChildChanges("/lgServer", new IZkChildListener() {
            public void handleChildChange(String serviceName, List<String> list) throws Exception {
                System.out.println("------获取注册服务信息----");
                getServerInfo();//重新获取注册信息
            }
        });
        //从各个服务节点下获取IP地址
        for (String serviceNode : servicesList) {
            String address = zkClient.readData("/lgServer" + "/" + serviceNode);
            zkMap.put(serviceNode,address);
        }
        System.out.println(zkMap);

    }
}
